#pragma once

#include <iostream>
#include <list>
#include <string>

/**
 * @brief 定义观察者接口
 *
 */
class Observer
{
public:
    virtual ~Observer(){};

public:
    virtual void update(const std::string &message) = 0;
};

/**
 * @brief 定义被观察者接口
 *
 */
class Subject
{
public:
    virtual ~Subject(){};

public:
    virtual void attach(Observer *observer) = 0;
    virtual void detach(Observer *observer) = 0;
    virtual void notify()                   = 0;
};

/**
 * @brief 定义黑板类(用于发布消息给所有观察者)
 *
 */
class Blackboard : public Subject
{
public:
    virtual ~Blackboard() override = default;

public:
    /**
     * @brief attach 方法，用于添加观察者
     *
     * @param observer 要添加的观察者
     */
    void attach(Observer *observer) override
    {
        m_observers.push_back(observer);
    };

    /**
     * @brief detach 方法，用于移除观察者
     *
     * @param observer 要移除的观察者
     */
    void detach(Observer *observer) override
    {
        m_observers.remove(observer);
    };

    /**
     * @brief notify 方法，用于通知所有观察者
     *
     */
    void notify() override
    {
        auto iter = m_observers.begin();
        while (iter != m_observers.end()) {
            (*iter)->update(m_message);
            iter++;
        }
    };

    void writeMessage(std::string message)
    {
        m_message = message;
        notify();
    }

private:
    std::list<Observer *> m_observers;
    std::string           m_message;
};

/**
 * @brief 定义学生类(用于订阅黑板上的消息)
 *
 */
class Student : public Observer
{
public:
    Student(std::string name, Subject &subject) : m_name(name), m_subject(subject)
    {
        this->m_subject.attach(this);
    }
    virtual ~Student(){};

public:
    void update(const std::string &message) override
    {
        std::cout << m_name << " received message: " << message << std::endl;
    }

    void removeObserver()
    {
        m_subject.detach(this);
    }

private:
    Subject    &m_subject;
    std::string m_name;
};
